{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# JavaでGUIプログラムを作る\n",
    "\n",
    "* ライブラリ\n",
    "    * AWT(Abstract Window Toolkit)\n",
    "        * GUIを使用したプログラムを開発するためのライブラリー\n",
    "        * Javaで作るGUIプログラムの基本\n",
    "        * 表示はプラットホームごとに異なる。\n",
    "    * Swing\n",
    "        * AWTの上部に作成されたライブラリーで機能が豊富\n",
    "        * 表示はすべてのプラットホームで同じ。\n",
    "    * SWT(Standard Widget Toolkit)\n",
    "        * IBMがEclipseのために開発したライブラリーで動作が軽快\n",
    "        * 表示はプラットホームごとに異なる\n",
    "        * プラットホームごとにSWT用のライブラリーが必要\n",
    "* プログラム内容\n",
    "    * 2つのクラス(PrefFrame, GUITest)と1つの無名内部クラス(ウィンドウを閉じる部分 new WindowAdapter〜)が作られる\n",
    "    * java.awt.event.*はイベント処理に必要なパッケージ\n",
    "        * イベント\n",
    "            * マウスでクリックしたりキーボードで入力する操作によって起こる状態の変化のこと\n",
    "            * 例えば、ウィンドウの閉じるボタンを押したときにイベントオブジェクトが発生する\n",
    "    * AWTでウィンドウを表示するにはFrameクラスを継承する\n",
    "        * Frameクラスだけではなく階層を遡って利用できる\n",
    "            * Rubyでは階層を遡ることはできない\n",
    "    * 内部クラス\n",
    "        * あるクラスの内部に定義するクラス\n",
    "            * 内部クラスのうち、名前をつけないで利用する場合は「無名内部クラス」という\n",
    "                * イベント処理でよく利用される\n",
    "                * <font color=\"red\">クラス名の代わりに「new スーパークラス名」を書く</font>\n",
    "            * コンパイルすると`$`の後に番号が振られたファイルができる\n",
    "                * `PrefFrame$1.class`\n",
    "    * java.awt.Colorクラス\n",
    "        * Colorクラスの定数で色を指定できる\n",
    "            * `frm.setBackground(Color.LIGHT_GRAY);`\n",
    "        * int型を引数にするとRGBカラーが使える\n",
    "            * `frm.setBackground(new Color(9, 150, 212));`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## AWTでウィンドウを表示する"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%%bash\n",
    "### 変数の設定\n",
    "name=GUITest\n",
    "#classpath=\".:/root/git_jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "#classpath=\".:/Users/ftakao2007/jupyter/jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "\n",
    "\n",
    "### ソースの編集\n",
    "cat <<- EOS > ${name}.java\n",
    "\n",
    "import java.awt.*;\n",
    "import java.awt.event.*;\n",
    "\n",
    "class PrefFrame extends Frame {\n",
    "  //# コンストラクタ\n",
    "  public PrefFrame(String title) {\n",
    "    //#フレームのタイトルの設定\n",
    "    setTitle(title);\n",
    "\n",
    "    //#ウィンドウを閉じる時のイベント処理。無名クラス\n",
    "    addWindowListener(new WindowAdapter() {\n",
    "      public void windowClosing(WindowEvent e) {\n",
    "        System.exit(0);\n",
    "      }\n",
    "    });\n",
    "  }\n",
    "}\n",
    "\n",
    "public class ${name} {\n",
    "  public static void main(String args[]){\n",
    "    //# PrefFrameクラスのインスタンスを生成。コンストラクタを呼び出している\n",
    "    PrefFrame frm = new PrefFrame(\"都道府県マスター\");\n",
    "    //# Frameクラスから継承したメソッドを利用\n",
    "    //# ウィンドウの表示位置\n",
    "    frm.setLocation(300, 200);\n",
    "    //# ウィンドウのサイズ\n",
    "    frm.setSize(250, 350);\n",
    "    //# ウィンドウの背景色\n",
    "    //# Color.LIGHT_GRAYはColorクラスの定数\n",
    "    frm.setBackground(Color.LIGHT_GRAY);\n",
    "    //# ウィンドウを表示する\n",
    "    frm.setVisible(true);\n",
    "  }\n",
    "}\n",
    "EOS\n",
    "\n",
    "### コンパイル\n",
    "#javac ${name}.java\n",
    "javac -encoding UTF-8 ${name}.java\n",
    "\n",
    "### 実行\n",
    "#java -classpath ${classpath} ${name}\n",
    "java  ${name}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1つのクラスから複数のWindowを表示する"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%%bash\n",
    "### 変数の設定\n",
    "name=GUITest2\n",
    "#classpath=\".:/root/git_jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "classpath=\".:/Users/ftakao2007/jupyter/jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "\n",
    "\n",
    "### ソースの編集\n",
    "cat <<- EOS > ${name}.java\n",
    "\n",
    "import java.awt.*;\n",
    "import java.awt.event.*;\n",
    "\n",
    "class PrefFrame extends Frame {\n",
    "  public PrefFrame(String title) {\n",
    "    setTitle(title);\n",
    "\n",
    "    addWindowListener(new WindowAdapter() {\n",
    "      public void windowClosing(WindowEvent e) {\n",
    "        System.exit(0);\n",
    "      }\n",
    "    });\n",
    "  }\n",
    "}\n",
    "\n",
    "public class ${name} {\n",
    "  public static void main(String args[]){\n",
    "    PrefFrame frm = new PrefFrame(\"都道府県マスター\");\n",
    "    frm.setLocation(300, 200);\n",
    "    frm.setSize(250, 350);\n",
    "    frm.setBackground(Color.LIGHT_GRAY);\n",
    "    frm.setVisible(true);\n",
    "    \n",
    "    //# 二つ目のWindow\n",
    "    PrefFrame frm2 = new PrefFrame(\"都道府県マスター2\");\n",
    "    frm2.setLocation(500, 200);\n",
    "    frm2.setSize(350, 450);\n",
    "    frm2.setBackground(new Color(255, 200, 0));\n",
    "    frm2.setVisible(true);\n",
    "  }\n",
    "}\n",
    "EOS\n",
    "\n",
    "### コンパイル\n",
    "#javac ${name}.java\n",
    "javac -encoding UTF-8 ${name}.java\n",
    "\n",
    "### 実行\n",
    "#java -classpath ${classpath} ${name}\n",
    "java ${name}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## コンストラクタにWindowの設定を書く"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%%bash\n",
    "### 変数の設定\n",
    "name=GUITest3\n",
    "#classpath=\".:/root/git_jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "#classpath=\".:/Users/ftakao2007/jupyter/jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "\n",
    "\n",
    "### ソースの編集\n",
    "cat <<- EOS > ${name}.java\n",
    "\n",
    "import java.awt.*;\n",
    "import java.awt.event.*;\n",
    "\n",
    "class PrefFrame extends Frame {\n",
    "  public PrefFrame(String title) {\n",
    "    setTitle(title);\n",
    "\n",
    "    addWindowListener(new WindowAdapter() {\n",
    "      public void windowClosing(WindowEvent e) {\n",
    "        System.exit(0);\n",
    "      }\n",
    "    });\n",
    "    \n",
    "    //# フレームの設定\n",
    "    setLocation(300,200);\n",
    "    setSize(250,350);\n",
    "    setBackground(Color.LIGHT_GRAY);\n",
    "  }\n",
    "}\n",
    "\n",
    "public class ${name} {\n",
    "  public static void main(String args[]){\n",
    "    PrefFrame frm = new PrefFrame(\"都道府県マスター\");\n",
    "    //# frmのインスタンスメソッドを実行\n",
    "    frm.setVisible(true);\n",
    "  }\n",
    "}\n",
    "EOS\n",
    "\n",
    "### コンパイル\n",
    "#javac ${name}.java\n",
    "javac -encoding UTF-8 ${name}.java\n",
    "\n",
    "### 実行\n",
    "#java -classpath ${classpath} ${name}\n",
    "java ${name}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## mainメソッドにWindowの設定を書く"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "### 変数の設定\n",
    "name=GUITest4\n",
    "#classpath=\".:/root/git_jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "#classpath=\".:/Users/ftakao2007/jupyter/jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "\n",
    "\n",
    "### ソースの編集\n",
    "cat <<- EOS > ${name}.java\n",
    "\n",
    "import java.awt.*;\n",
    "import java.awt.event.*;\n",
    "\n",
    "class ${name} extends Frame {\n",
    "\n",
    "    public static void main(String args[]){\n",
    "        //# クラス自身のインスタンスを生成\n",
    "        ${name} frm = new ${name}(\"都道府県マスター\");\n",
    "    }\n",
    "\n",
    "    public ${name}(String title) {\n",
    "        setTitle(title);\n",
    "\n",
    "        addWindowListener(new WindowAdapter() {\n",
    "          public void windowClosing(WindowEvent e) {\n",
    "            System.exit(0);\n",
    "          }\n",
    "        });\n",
    "    \n",
    "        //# フレームの設定\n",
    "        setLocation(300,200);\n",
    "        setSize(250,350);\n",
    "        setBackground(Color.LIGHT_GRAY);\n",
    "        //# frmのインスタンメソッドではなくクラスメソッドでインスタンスを生成せず実行\n",
    "        //# mainメソッドはstaticなので可能\n",
    "        setVisible(true);\n",
    "  }\n",
    "}\n",
    "EOS\n",
    "\n",
    "### コンパイル\n",
    "#javac ${name}.java\n",
    "javac -encoding UTF-8 ${name}.java\n",
    "\n",
    "### 実行\n",
    "#java -classpath ${classpath} ${name}\n",
    "java ${name}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 画面のレイアウトとイベント処理\n",
    "\n",
    "* コンポーネント\n",
    "    * GUIオブジェクトのこと\n",
    "        * ボタン\n",
    "        * ラベル\n",
    "        * テキストフィールド\n",
    "        * テキストエリア\n",
    "        * スクロールバー\n",
    "        * etc..\n",
    "    * メソッド外で定義する\n",
    "        * クラス内の各メソッドから参照できるようにするため\n",
    "    * アクセス修飾子は「指定無し」\n",
    "        * テスト用クラスから参照することもあるため\n",
    "* コンテナ\n",
    "    * コンポーネントを格納するもの\n",
    "        * コンテナは他のコンテンを格納することもできる\n",
    "            * (ここではPanelクラスのインスタンス(オブジェクト)がコンテナ？)\n",
    "            * (Frameクラスのオブジェクトもコンテナ？)\n",
    "    * 「レイアウトマネージャ」がある\n",
    "        * コンポーネントをどのように配置するかを制御する\n",
    "        * setLayout()メソッドでどのレイアウトを使うか指定する\n",
    "* レイアウト\n",
    "    * 主なレイアウト\n",
    "        * FlowLayout\n",
    "            * Pannelクラスのデフォルト(初期設定)\n",
    "        * GridLayout\n",
    "            * ここのPannelクラスで指定したレイアウト\n",
    "        * BorderLayout\n",
    "            * Frameクラスのデフォルト(初期設定)\n",
    "        * GridBagLayout\n",
    "        * CardLayout\n",
    "* イベント(出来事)\n",
    "    * マウスやキーボードの操作、ボタンのクリックなどによって発生した状態の変化\n",
    "    * イベントソース\n",
    "        * イベントのきっかけになったボタンなど\n",
    "    * イベント処理\n",
    "        * 各イベントに対応した処理を行うこと\n",
    "    * イベントリスナー\n",
    "        * イベントを検出できるように監視する役割\n",
    "        * イベントリスナーインターフェースを実装し、イベントに対応したイベントハンドラをオーバーライドしたクラス\n",
    "        * イベントリスナーはウィンドウの時もあればラベルなどのコンポーネントの時もある\n",
    "            * イベントリスナーとしての機能を実装していれば良い\n",
    "    * イベントが発生\n",
    "        * イベントオブジェクトが発生\n",
    "        * イベントハンドラで受け取る\n",
    "        * 予めプログラムした処理を行う\n",
    "    * 今回の例\n",
    "        * イベントリスナーインターフェイスを実装\n",
    "            * `class PrefFrame extends Frame implements ActionListener {`\n",
    "            * `ActionListener` がインターフェイス\n",
    "        * イベントリスナー登録メソッド\n",
    "            * `btn1.addActionListener(this);`\n",
    "            * btn1はイベントソース\n",
    "            * addActionListener()はButtonクラスのメソッド\n",
    "            * thisはイベントリスナーであるウィンドウ(オブジェクト自身)\n",
    "        * イベントハンドラ\n",
    "            * `actionPerformed (ActionEvent e)`\n",
    "            * イベントに対応したメソッドをオーバーライドしているところ\n",
    "            * eにはイベント情報が渡される"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "### 変数の設定\n",
    "name=GUITest5\n",
    "#classpath=\".:/root/git_jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "#classpath=\".:/Users/ftakao2007/jupyter/jupyter_notebook/Java/postgresql-42.1.1.jar\"\n",
    "\n",
    "\n",
    "### ソースの編集\n",
    "cat <<- EOS > ${name}.java\n",
    "\n",
    "import java.awt.*;\n",
    "import java.awt.event.*;\n",
    "\n",
    "class PrefFrame extends Frame implements ActionListener {\n",
    "    //# コンポーネントを定義。各クラスのメソッドが利用できるようにメソッド外で定義する\n",
    "    Label lb1;\n",
    "    TextArea txtar1;\n",
    "    Button btn1, btn2, btn3;\n",
    "    \n",
    "    public PrefFrame(String title) {\n",
    "        setTitle(title);\n",
    "\n",
    "        addWindowListener(new WindowAdapter() {\n",
    "            public void windowClosing(WindowEvent e) {\n",
    "                System.exit(0);\n",
    "            }\n",
    "        });\n",
    "\n",
    "        //# ラベル。BorderLayoutの頭にラベルを表示\n",
    "        lb1 = new Label(\"ボタンをクリックしてください。\",Label.CENTER);\n",
    "        add(lb1, BorderLayout.NORTH);\n",
    "        \n",
    "        //# テキストエリア。BorderLayoutの中央にテキストエリアを表示\n",
    "        txtar1 = new TextArea();\n",
    "        add(txtar1, BorderLayout.CENTER);\n",
    "        \n",
    "        //# パネル。GridLayoutを指定\n",
    "        Panel pn1 = new Panel();\n",
    "        pn1.setLayout(new GridLayout(1, 3));\n",
    "        \n",
    "        //# ボタンの設定とパネルへ追加\n",
    "        btn1 = new Button(\"表示\");\n",
    "        //# thisはイベントリスナーのウィンドウ。これをイベントソースのボタンに登録している\n",
    "        btn1.addActionListener(this);\n",
    "        //# パネルに追加している\n",
    "        pn1.add(btn1);\n",
    "        \n",
    "        //# ボタンの設定とパネルへ追加\n",
    "        btn2 = new Button(\"クリア\");\n",
    "        btn2.addActionListener(this);\n",
    "        pn1.add(btn2);\n",
    "\n",
    "        //# ボタンの設定とパネルへ追加\n",
    "        btn3 = new Button(\"終了\");\n",
    "        btn3.addActionListener(this);\n",
    "        pn1.add(btn3);\n",
    "        \n",
    "        //# パネル。BorderLayoutの下にパネルを表示\n",
    "        add(pn1, BorderLayout.SOUTH);\n",
    "    }\n",
    "  \n",
    "    //# イベントが発生すると呼び出されるイベントハンドラのactionPerfomed()メソッド\n",
    "    public void actionPerformed (ActionEvent e) {\n",
    "        if (e.getSource() == btn1) {\n",
    "            //# ボタン1(表示)を押した時はprefDisplayメソッドを実行\n",
    "            prefDisplay();\n",
    "        } else if (e.getSource() == btn2) {\n",
    "            //# ボタン2(クリア)を押した時はクリアする\n",
    "            txtar1.setText(\"\");\n",
    "        } else {\n",
    "            //# ボタン3(終了)を押した時は終了する\n",
    "            System.exit(0);\n",
    "        }\n",
    "    }\n",
    "    \n",
    "    //# クラス内からしか使わないのでアクセス修飾子はprivate\n",
    "    private void prefDisplay () {\n",
    "        //# Stringでは固定文字列で文字を追加するたびにインスタンスを作り直すので効率が悪い\n",
    "        StringBuffer temp = new StringBuffer();\n",
    "        temp.append(\"1\" + \"\\t\");\n",
    "        temp.append(\"Hokkaido\" + \"\\n\");\n",
    "        temp.append(\"2\" + \"\\t\");\n",
    "        temp.append(\"Aomori\" + \"\\n\");\n",
    "        temp.append(\"3\" + \"\\t\");\n",
    "        temp.append(\"Iwate\" + \"\\n\");\n",
    "        temp.append(\"4\" + \"\\t\");\n",
    "        temp.append(\"Miyagi\" + \"\\n\");\n",
    "        temp.append(\"5\" + \"\\t\");\n",
    "        temp.append(\"Akita\" + \"\\n\");\n",
    "        //# 最後にtoString()メソッドで文字列を得ている\n",
    "        txtar1.setText(temp.toString());\n",
    "    }\n",
    "            \n",
    "}\n",
    "\n",
    "public class $name {\n",
    "    public static void main(String args[]){\n",
    "        PrefFrame frm = new PrefFrame(\"都道府県マスター\");\n",
    "        //# フレームの設定\n",
    "        frm.setLocation(300,200);\n",
    "        frm.setSize(250,350);\n",
    "        frm.setBackground(Color.LIGHT_GRAY);\n",
    "        frm.setVisible(true);\n",
    "    }\n",
    "}\n",
    "EOS\n",
    "\n",
    "### コンパイル\n",
    "#javac ${name}.java\n",
    "javac -encoding UTF-8 ${name}.java\n",
    "\n",
    "### 実行\n",
    "#java -classpath ${classpath} ${name}\n",
    "java ${name}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
